<template>
  <div bg="#fff" px-2>
    <search ref="queryEl" :searchFormSchema="searchFormSchema" :searchActions="searchActions" v-model="state.tableSearchData"
      @handleOperateAction="handleOperateAction" :inline="true"></search>
    <div class="opt-container overflow-hidden">
      <div class="m-1 border-t border-gray-light"></div>
      <div class="table_opt-btns flex flex-wrap justify-end mb-2">
        <div v-for="(action, index) in props.tableActions" class="mr-2">
          <el-button :type="action.style" :size="action.size || 'small'" :icon="action.icon" @click="handleTableOperate(action)">{{ action.label }}</el-button>
        </div>
      </div>
    </div>
    <el-table :data="state.tableData" :height="sysStyle.tableHeight" class="px-2" append>
      <el-table-column v-for="item in tableTypeFields" :width="item.width" :align="item.align || 'center'"
        :type="item.type" :label="item.label">
      </el-table-column>
      <el-table-column v-for="item in tableFields" :show-overflow-tooltip="!!item.showOverflowTooltip || false"
        :prop="item.field" :label="item.label" :width="item.width" :align="item.align || 'center'">
        <template #default="scope">
          <slot :name="item.field" :row="scope.row">{{ scope.row[item.field] }}</slot>
        </template>
      </el-table-column>
      <el-table-column fixed="right" label="操作" align="center">
        <template #default>
          <div class="flex justify-center">
            <el-button v-for="(action, index) in props.tableRowActions" class="" :type="action.style" :size="action.size || 'small'" :icon="action.icon" @click="handleTableOperate(action)">{{ action.label }}</el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-model:current-page="state.queryParams.pageIndex" v-model:page-size="state.queryParams.pageSize"
      :total="state.total"></pagination>
    <Upload ref="uploadRef" v-bind="uploadOptions" @uploadSuccess="uploadSuccess"></Upload>
    <form-drawer v-model:showDrawer="showDrawer" :form-actions="formActions" :schema="props.formSchema"></form-drawer>
  </div>
</template>

<script lang="ts" setup>
import { useSysStyleStore } from '@/store/sysStyle';
import service from '@/utils/request';
import { ElMessage, UploadProps } from 'element-plus';
import { FormActionsType, FormButtonType, FormDataRowType } from 'types/form';
import { RequestConfigType } from 'types/request';
import { TableDataTypeRow, TableQueryParamsType, TableSearchSchemaRowType } from 'types/table';
import { computed, markRaw, nextTick, onMounted, reactive, ref, watch } from 'vue';

interface TablePropTypes {
  url: string,
  config?: RequestConfigType,
  params?: TableQueryParamsType,
  data?: unknown,
  searchFormSchema?: TableSearchSchemaRowType[],
  formSchema?: FormDataRowType[],
  fields: TableDataTypeRow[],
  searchActions?: FormButtonType[],
  tableActions?: FormButtonType[],
  tableRowActions?: FormButtonType[],
  formActions?: FormButtonType[]
  uploadOptions?: UploadProps
}

interface StateDataType {
  tableData: unknown[],
  config?: RequestConfigType,
  total: number,
  queryParams: TableQueryParamsType,
  formData?: any,
  tableSearchData?: Object
}

const props = defineProps<TablePropTypes>()

const queryEl: any = ref(null)
const showDrawer = ref(false)
const uploadRef: any = ref<InstanceType<typeof uploadRef>>()

const sysStyle = useSysStyleStore()

let searchHeight = ref(0)
const uploadOptions = reactive({
  ...props.uploadOptions
})

onMounted(async () => {
  const requestUrl = props?.url
  nextTick(() => {
    getDataList(requestUrl, state.queryParams)
  })
})

nextTick(() => {
  setTimeout(() => {    
    setSearchHeight()
  }, 1000);
})


// init state data
let state = reactive<StateDataType>({
  tableData: [],
  queryParams: {
    pageIndex: 1,
    pageSize: 20
  },
  config: props.config,
  total: 0,
  tableSearchData: {}
})

const searchFormSchema = computed(() => {
  return props?.searchFormSchema
})
const searchActions = computed(() => {
  return props?.searchActions || []
})
const tableFields = computed(() => {
  return props?.fields.filter(e => !!e.field)
})
const tableTypeFields = computed(() => {
  return props?.fields.filter(e => !!e.type)
})

const setSearchHeight = () => {
  const el = queryEl
  searchHeight.value = el.value.searchRef.offsetHeight
  sysStyle.setSearchHeight(searchHeight.value)
}

watch(() => state.queryParams, (n: TableQueryParamsType) => {
  getDataList(props.url, n)
}, { deep: true })


const getDataList = (url: string = props.url, queryParams: TableQueryParamsType = state.queryParams): any => {
  
  const options = Object.assign({}, { params: { ...queryParams, ...props.params, ...state.tableSearchData } }, props.config)
  service.get(url, options).then((result: any) => {
    state.tableData = markRaw(result.data.list)
    state.total = result.data.total || result.data.length
  })
}

const searchData = () => {
  getDataList()
}

const handleTableOperate = (action:FormButtonType) => {
  
  switch (action.type) {
    case 'export':
      
      break;
    case 'import':
      uploadRef.value?.handleOpenUpload()
      break;
    case 'add':
      showDrawer.value = true
      
      break;
    case 'delete':
      
      break;
    case 'update':
      showDrawer.value = true
      break;
  
    default:
      break;
  }
}

/**
 * @description: 重置表格搜索内容
 */
const reset = () => {
  state.tableSearchData = undefined
  getDataList()
}

/**
 * 
 * @param action 表格搜索区域操作
 * @param data 
 */
const handleOperateAction = (action: FormActionsType, data: unknown) => {
  searchActions.value.forEach((e: any) => {
    if (e.type === action && e.handleOperate) {
      e.handleOperate()
    } else if (e.type == action) {
      switch (action) {
        case 'reset':
          reset()
          break;
        case 'search':
          state.tableSearchData = data.value
          searchData()
          break;
        case 'submit':

          break;
        default:
          break;
      }
    }
  })
}

const uploadSuccess = (args: any) => {
  getDataList()
  ElMessage.success('上传成功')
  
}

const handleClick = () => {

}


</script>


<style lang="scss" scoped></style>